Python-da Circuit Breaker pattern-ni qanday amalga oshirishni o'rganing va xatolarga chidamli va barqaror ilovalarni yarating. Kaskadli nosozliklarning oldini oling va tizim barqarorligini yaxshilang.
Python Circuit Breaker: Xatolarga Chidamli Ilovalarni Yaratish
Taqsimlangan tizimlar va mikroservislar dunyosida nosozliklar bilan ishlash muqarrar. Xizmatlar tarmoq muammolari, ortiqcha yuklangan serverlar yoki kutilmagan xatolar tufayli mavjud bo'lmay qolishi mumkin. Agar ishlamay qolgan xizmat to'g'ri ishlanmasa, bu butun tizimlarni ishdan chiqarib, kaskadli nosozliklarga olib kelishi mumkin. Circuit Breaker pattern ushbu kaskadli nosozliklarning oldini olish va yanada barqaror ilovalarni yaratish uchun kuchli texnikadir. Ushbu maqola Python-da Circuit Breaker pattern-ni amalga oshirish bo'yicha keng qamrovli qo'llanmani taqdim etadi.
Circuit Breaker Pattern nima?
Elektr kontaktlarning uzilishidan ilhomlangan Circuit Breaker pattern ishlamay qolishi mumkin bo'lgan operatsiyalar uchun proksi sifatida ishlaydi. U ushbu operatsiyalarning muvaffaqiyat va muvaffaqiyatsizlik darajasini kuzatib boradi va muvaffaqiyatsizliklarning ma'lum bir chegarasiga yetganda, ishlamay qolgan xizmatga keyingi qo'ng'iroqlarning oldini olib, kontaktni "o'chiradi". Bu ishlamay qolgan xizmatga so'rovlar bilan to'lib ketmasdan tiklanishga vaqt beradi va chaqiruvchi xizmatga ma'lum bo'lgan xizmatga ulanishga urinish uchun resurslarni behuda sarflashning oldini oladi.
Circuit Breaker uchta asosiy holatga ega:
- Yopiq: Circuit breaker o'zining normal holatida bo'lib, qo'ng'iroqlarning himoyalangan xizmatga o'tishiga imkon beradi. U ushbu qo'ng'iroqlarning muvaffaqiyati va muvaffaqiyatsizligini kuzatib boradi.
- Ochiq: Circuit breaker o'chirilgan va himoyalangan xizmatga barcha qo'ng'iroqlar bloklangan. Belgilangan taym-aut davridan so'ng, circuit breaker Yarim Ochiq holatga o'tadi.
- Yarim Ochiq: Circuit breaker himoyalangan xizmatga cheklangan miqdordagi test qo'ng'iroqlariga ruxsat beradi. Agar ushbu qo'ng'iroqlar muvaffaqiyatli bo'lsa, circuit breaker Yopiq holatga qaytadi. Agar ular ishlamay qolsa, u Ochiq holatga qaytadi.
Mana oddiy o'xshashlik: Tasavvur qiling-a, siz bankomatdan pul yechib olishga harakat qilyapsiz. Agar bankomat qayta-qayta naqd pul bermasa (ehtimol bankdagi tizim xatosi tufayli), Circuit Breaker ishga tushadi. Muvaffaqiyatsiz bo'lishi mumkin bo'lgan pul yechishga urinishni davom ettirish o'rniga, Circuit Breaker vaqtincha keyingi urinishlarni bloklaydi (Ochiq holat). Biroz vaqt o'tgach, u bitta pul yechishga urinishga ruxsat berishi mumkin (Yarim Ochiq holat). Agar bu urinish muvaffaqiyatli bo'lsa, Circuit Breaker normal ishlashni davom ettiradi (Yopiq holat). Agar ishlamay qolsa, Circuit Breaker uzoqroq vaqt davomida Ochiq holatda qoladi.
Nima uchun Circuit Breaker-dan foydalanish kerak?
Circuit Breaker-ni amalga oshirish bir qator afzalliklarni taqdim etadi:
- Kaskadli nosozliklarning oldini oladi: Ishlamay qolgan xizmatga qo'ng'iroqlarni bloklash orqali Circuit Breaker nosozlikning tizimning boshqa qismlariga tarqalishining oldini oladi.
- Tizim barqarorligini yaxshilaydi: Circuit Breaker ishlamay qolgan xizmatlarga so'rovlar bilan to'lib ketmasdan tiklanishga vaqt beradi, bu esa yanada barqaror va chidamli tizimga olib keladi.
- Resurs sarfini kamaytiradi: Ishlamay qolgan xizmatga keraksiz qo'ng'iroqlardan qochish orqali Circuit Breaker chaqiruvchi va chaqirilgan xizmatdagi resurs sarfini kamaytiradi.
- Zaxira mexanizmlarini ta'minlaydi: Kontakt ochiq bo'lganda, chaqiruvchi xizmat zaxira mexanizmini, masalan, keshlangan qiymatni qaytarish yoki xato xabarini ko'rsatish kabi yaxshiroq foydalanuvchi tajribasini ta'minlaydigan zaxira mexanizmini bajarishi mumkin.
Python-da Circuit Breaker-ni amalga oshirish
Python-da Circuit Breaker pattern-ni amalga oshirishning bir necha yo'li mavjud. Siz o'zingizning implementatsiyangizni noldan qurishingiz yoki uchinchi tomon kutubxonasidan foydalanishingiz mumkin. Bu yerda biz ikkala yondashuvni ham o'rganamiz.
1. Maxsus Circuit Breaker qurish
Asosiy tushunchalarni tushunish uchun asosiy, maxsus implementatsiyadan boshlaylik. Ushbu misolda oqim xavfsizligi uchun `threading` moduli va taym-autlarni boshqarish uchun `time` moduli ishlatiladi.
import time
import threading
class CircuitBreaker:
def __init__(self, failure_threshold, recovery_timeout):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.state = "CLOSED"
self.failure_count = 0
self.last_failure_time = None
self.lock = threading.Lock()
def call(self, func, *args, **kwargs):
with self.lock:
if self.state == "OPEN":
if time.time() - self.last_failure_time > self.recovery_timeout:
self.state = "HALF_OPEN"
else:
raise CircuitBreakerError("Circuit breaker is open")
try:
result = func(*args, **kwargs)
self.reset()
return result
except Exception as e:
self.record_failure()
raise e
def record_failure(self):
with self.lock:
self.failure_count += 1
self.last_failure_time = time.time()
if self.failure_count >= self.failure_threshold:
self.state = "OPEN"
print("Circuit breaker opened")
def reset(self):
with self.lock:
self.failure_count = 0
self.state = "CLOSED"
print("Circuit breaker closed")
class CircuitBreakerError(Exception):
pass
# Example Usage
def unreliable_service():
# Simulate a service that sometimes fails
import random
if random.random() < 0.5:
raise Exception("Service failed")
else:
return "Service successful"
circuit_breaker = CircuitBreaker(failure_threshold=3, recovery_timeout=10)
for i in range(10):
try:
result = circuit_breaker.call(unreliable_service)
print(f"Call {i+1}: {result}")
except CircuitBreakerError as e:
print(f"Call {i+1}: {e}")
except Exception as e:
print(f"Call {i+1}: Service failed: {e}")
time.sleep(1)
Izoh:
- `CircuitBreaker` Class:
- `__init__(self, failure_threshold, recovery_timeout)`: Circuit breaker-ni muvaffaqiyatsizlik chegarasi (kontaktni o'chirishdan oldin muvaffaqiyatsizliklar soni), tiklanish taym-auti (yarim ochiq holatga urinishdan oldin kutish vaqti) bilan ishga tushiradi va dastlabki holatni `CLOSED` ga o'rnatadi.
- `call(self, func, *args, **kwargs)`: Bu siz himoya qilmoqchi bo'lgan funksiyani o'rab oladigan asosiy usul. U circuit breaker-ning joriy holatini tekshiradi. Agar u `OPEN` bo'lsa, tiklanish taym-auti o'tganligini tekshiradi. Agar shunday bo'lsa, u `HALF_OPEN` ga o'tadi. Aks holda, u `CircuitBreakerError` ni ko'taradi. Agar holat `OPEN` bo'lmasa, u funksiyani bajaradi va potentsial istisnolarni qayta ishlaydi.
- `record_failure(self)`: Muvaffaqiyatsizliklar sonini oshiradi va muvaffaqiyatsizlik vaqtini yozib oladi. Agar muvaffaqiyatsizliklar soni chegara qiymatidan oshsa, u kontaktni `OPEN` holatiga o'tkazadi.
- `reset(self)`: Muvaffaqiyatsizliklar sonini tiklaydi va kontaktni `CLOSED` holatiga o'tkazadi.
- `CircuitBreakerError` Class: Circuit breaker ochiq bo'lganda ko'tarilgan maxsus istisno.
- `unreliable_service()` Function: Tasodifiy ravishda ishlamay qoladigan xizmatni simulyatsiya qiladi.
- Example Usage: `unreliable_service()` funksiyasini himoya qilish uchun `CircuitBreaker` klassidan qanday foydalanishni ko'rsatadi.
Maxsus implementatsiya uchun asosiy fikrlar:
- Oqim xavfsizligi: `threading.Lock()` oqim xavfsizligini ta'minlash uchun juda muhim, ayniqsa bir vaqtning o'zida ishlaydigan muhitlarda.
- Xatolarni qayta ishlash: `try...except` bloki himoyalangan xizmatdan keladigan istisnolarni ushlaydi va `record_failure()` ni chaqiradi.
- Holat o'tishlari: `CLOSED`, `OPEN` va `HALF_OPEN` holatlari orasidagi o'tish mantig'i `call()` va `record_failure()` usullari ichida amalga oshiriladi.
2. Uchinchi tomon kutubxonasidan foydalanish: `pybreaker`
O'z Circuit Breaker-ni qurish yaxshi o'rganish tajribasi bo'lishi mumkin bo'lsa-da, yaxshi sinovdan o'tgan uchinchi tomon kutubxonasidan foydalanish ko'pincha ishlab chiqarish muhitlari uchun yaxshiroq variantdir. Circuit Breaker pattern-ni amalga oshirish uchun mashhur Python kutubxonalaridan biri `pybreaker` dir.
O'rnatish:
pip install pybreaker
Misol foydalanish:
import pybreaker
import time
# Define a custom exception for our service
class ServiceError(Exception):
pass
# Simulate an unreliable service
def unreliable_service():
import random
if random.random() < 0.5:
raise ServiceError("Service failed")
else:
return "Service successful"
# Create a CircuitBreaker instance
circuit_breaker = pybreaker.CircuitBreaker(
fail_max=3, # Number of failures before opening the circuit
reset_timeout=10, # Time in seconds before attempting to close the circuit
name="MyService"
)
# Wrap the unreliable service with the CircuitBreaker
@circuit_breaker
def call_unreliable_service():
return unreliable_service()
# Make calls to the service
for i in range(10):
try:
result = call_unreliable_service()
print(f"Call {i+1}: {result}")
except pybreaker.CircuitBreakerError as e:
print(f"Call {i+1}: Circuit breaker is open: {e}")
except ServiceError as e:
print(f"Call {i+1}: Service failed: {e}")
time.sleep(1)
Izoh:
- O'rnatish: `pip install pybreaker` buyrug'i kutubxonani o'rnatadi.
- `pybreaker.CircuitBreaker` Class:
- `fail_max`: Circuit breaker ochilishidan oldin ketma-ket muvaffaqiyatsizliklar sonini belgilaydi.
- `reset_timeout`: Circuit breaker yarim ochiq holatga o'tishdan oldin ochiq qoladigan vaqtni (soniyalarda) belgilaydi.
- `name`: Circuit breaker uchun tavsiflovchi nom.
- Dekorator: `@circuit_breaker` dekoratori `unreliable_service()` funksiyasini o'rab oladi, avtomatik ravishda circuit breaker mantig'ini boshqaradi.
- Xatolarni qayta ishlash: `try...except` bloki kontakt ochiq bo'lganda `pybreaker.CircuitBreakerError` va xizmat ishlamay qolganda `ServiceError` (bizning maxsus istisnomiz) ni ushlaydi.
`pybreaker` dan foydalanish afzalliklari:
- Soddalashtirilgan implementatsiya: `pybreaker` toza va ishlatish uchun qulay API-ni taqdim etadi, bu esa boilerplate kodini kamaytiradi.
- Oqim xavfsizligi: `pybreaker` oqim xavfsiz, bu uni bir vaqtning o'zida ishlaydigan ilovalar uchun mos qiladi.
- Moslashtiriladigan: Siz turli xil parametrlarni, masalan, muvaffaqiyatsizlik chegarasi, qayta o'rnatish taym-auti va voqea tinglovchilarini sozlashingiz mumkin.
- Voqea tinglovchilari: `pybreaker` voqea tinglovchilarini qo'llab-quvvatlaydi, bu sizga circuit breaker holatini kuzatish va shunga mos ravishda harakat qilish imkonini beradi (masalan, jurnalga yozish, ogohlantirishlar yuborish).
3. Kengaytirilgan Circuit Breaker tushunchalari
Asosiy implementatsiyadan tashqari, Circuit Breaker-lardan foydalanganda hisobga olish kerak bo'lgan bir nechta kengaytirilgan tushunchalar mavjud:
- Metrikalar va monitoring: Circuit Breaker-laringizning ishlashini kuzatib borish ularning xatti-harakatlarini tushunish va potentsial muammolarni aniqlash uchun zarurdir. Prometheus va Grafana kabi kutubxonalar ushbu metrikalarni vizualizatsiya qilish uchun ishlatilishi mumkin. Quyidagi kabi metrikalarni kuzatib boring:
- Circuit Breaker holati (Ochiq, Yopiq, Yarim Ochiq)
- Muvaffaqiyatli qo'ng'iroqlar soni
- Muvaffaqiyatsiz qo'ng'iroqlar soni
- Qo'ng'iroqlar kechikishi
- Zaxira mexanizmlari: Kontakt ochiq bo'lganda, so'rovlarni qayta ishlash strategiyasi kerak. Umumiy zaxira mexanizmlari quyidagilarni o'z ichiga oladi:
- Keshlangan qiymatni qaytarish.
- Foydalanuvchiga xato xabarini ko'rsatish.
- Muqobil xizmatga qo'ng'iroq qilish.
- Standart qiymatni qaytarish.
- Asinxron Circuit Breaker-lar: Asinxron ilovalarda (`asyncio` dan foydalangan holda) siz asinxron Circuit Breaker implementatsiyasidan foydalanishingiz kerak bo'ladi. Ba'zi kutubxonalar asinxron qo'llab-quvvatlashni taklif qiladi.
- Bulkheadlar: Bulkhead pattern ilovaning bir qismidagi nosozliklarning boshqalarga tarqalishining oldini olish uchun ularni ajratib turadi. Circuit Breaker-lar Bulkheadlar bilan birgalikda ishlatilishi mumkin, hatto undan ham katta xatolarga chidamlilikni ta'minlash uchun.
- Vaqtga asoslangan Circuit Breaker-lar: Muvaffaqiyatsizliklar sonini kuzatish o'rniga, vaqtga asoslangan Circuit Breaker, agar himoyalangan xizmatning o'rtacha javob berish vaqti ma'lum bir vaqt oralig'ida ma'lum bir chegaradan oshib ketgan bo'lsa, kontaktni ochadi.
Amaliy misollar va foydalanish holatlari
Turli xil stsenariylarda Circuit Breaker-lardan qanday foydalanishingiz mumkinligiga bir nechta amaliy misollar keltirilgan:
- Mikroservislar arxitekturasi: Mikroservislar arxitekturasida xizmatlar ko'pincha bir-biriga bog'liq bo'ladi. Circuit Breaker quyi oqimdagi xizmatdagi nosozliklar bilan to'lib ketishdan xizmatni himoya qilishi mumkin. Misol uchun, elektron tijorat ilovasi mahsulot katalogi, buyurtmani qayta ishlash va to'lovlarni qayta ishlash uchun alohida mikroservislarga ega bo'lishi mumkin. Agar to'lovlarni qayta ishlash xizmati mavjud bo'lmay qolsa, buyurtmani qayta ishlash xizmatidagi Circuit Breaker yangi buyurtmalar yaratilishining oldini olishi mumkin, bu kaskadli nosozlikning oldini oladi.
- Ma'lumotlar bazasi ulanishlari: Agar sizning ilovangiz tez-tez ma'lumotlar bazasiga ulanib tursa, Circuit Breaker ma'lumotlar bazasi mavjud bo'lmaganda ulanish bo'ronlarining oldini olishi mumkin. Geografik jihatdan taqsimlangan ma'lumotlar bazasiga ulanadigan ilovani ko'rib chiqing. Agar tarmoq ishdan chiqishi ma'lumotlar bazasi mintaqalaridan biriga ta'sir qilsa, Circuit Breaker ilovaning mavjud bo'lmagan mintaqaga qayta-qayta ulanishga urinishining oldini olishi, ishlash va barqarorlikni yaxshilashi mumkin.
- Tashqi API-lar: Tashqi API-larga qo'ng'iroq qilganda, Circuit Breaker ilovangizni vaqtinchalik xatolar va uzilishlardan himoya qilishi mumkin. Ko'pgina tashkilotlar turli xil funksiyalar uchun uchinchi tomon API-lariga tayanadi. API qo'ng'iroqlarini Circuit Breaker bilan o'rash orqali tashkilotlar yanada mustahkam integratsiyalarni yaratishi va tashqi API nosozliklarining ta'sirini kamaytirishi mumkin.
- Qayta urinish mantig'i: Circuit Breaker-lar qayta urinish mantig'i bilan birgalikda ishlashi mumkin. Biroq, muammoni yanada kuchaytirishi mumkin bo'lgan tajovuzkor qayta urinishlardan qochish muhimdir. Circuit Breaker xizmat mavjud bo'lmaganda qayta urinishlarning oldini olishi kerak.
Global mulohazalar
Global kontekstda Circuit Breaker-larni amalga oshirishda quyidagilarni hisobga olish muhimdir:
- Tarmoq kechikishi: Tarmoq kechikishi chaqiruvchi va chaqirilgan xizmatlarning geografik joylashuviga qarab sezilarli darajada farq qilishi mumkin. Tiklanish taym-autini shunga mos ravishda sozlang. Misol uchun, Shimoliy Amerika va Evropadagi xizmatlar o'rtasidagi qo'ng'iroqlar bir xil mintaqadagi qo'ng'iroqlarga qaraganda yuqori kechikishga ega bo'lishi mumkin.
- Vaqt zonalari: Barcha vaqt tamg'alari turli vaqt zonalarida izchil ishlanishini ta'minlang. Vaqt tamg'alarini saqlash uchun UTC dan foydalaning.
- Mintaqaviy uzilishlar: Mintaqaviy uzilishlar ehtimolini ko'rib chiqing va nosozliklarni muayyan mintaqalar bilan cheklash uchun Circuit Breaker-larni amalga oshiring.
- Madaniy mulohazalar: Zaxira mexanizmlarini loyihalashda foydalanuvchilaringizning madaniy kontekstini hisobga oling. Misol uchun, xato xabarlari mahalliy va madaniy jihatdan mos bo'lishi kerak.
Eng yaxshi amaliyotlar
Circuit Breaker-lardan samarali foydalanish uchun ba'zi eng yaxshi amaliyotlar:
- Konservativ sozlamalardan boshlang: Nisbatan past muvaffaqiyatsizlik chegarasi va uzoqroq tiklanish taym-auti bilan boshlang. Circuit Breaker-ning xatti-harakatlarini kuzatib boring va sozlamalarni kerak bo'lganda sozlang.
- Mos zaxira mexanizmlaridan foydalaning: Yaxshi foydalanuvchi tajribasini ta'minlaydigan va nosozliklarning ta'sirini kamaytiradigan zaxira mexanizmlarini tanlang.
- Circuit Breaker holatini kuzatib boring: Circuit Breaker-laringizning holatini kuzatib boring va kontakt ochiq bo'lganda sizga xabar berish uchun ogohlantirishlarni o'rnating.
- Circuit Breaker xatti-harakatini sinovdan o'tkazing: Circuit Breaker-laringiz to'g'ri ishlayotganligini ta'minlash uchun sinov muhitingizda nosozliklarni simulyatsiya qiling.
- Circuit Breaker-larga haddan tashqari ishonishdan saqlaning: Circuit Breaker-lar nosozliklarni yumshatish uchun vositadir, lekin ular ushbu nosozliklarning asosiy sabablarini bartaraf etish o'rnini bosmaydi. Xizmat beqarorligining asosiy sabablarini o'rganing va tuzating.
- Taqsimlangan kuzatuvni ko'rib chiqing: So'rovlarni bir nechta xizmat bo'ylab kuzatish uchun taqsimlangan kuzatuv vositalarini (masalan, Jaeger yoki Zipkin) integratsiya qiling. Bu sizga nosozliklarning asosiy sababini aniqlashga va Circuit Breaker-larning umumiy tizimga ta'sirini tushunishga yordam beradi.
Xulosa
Circuit Breaker pattern xatolarga chidamli va barqaror ilovalarni yaratish uchun qimmatli vositadir. Kaskadli nosozliklarning oldini olish va ishlamay qolgan xizmatlarga tiklanishga vaqt berish orqali Circuit Breaker-lar tizim barqarorligi va mavjudligini sezilarli darajada yaxshilashi mumkin. O'zingizning implementatsiyangizni yaratishni yoki `pybreaker` kabi uchinchi tomon kutubxonasidan foydalanishni tanlaysizmi, Circuit Breaker pattern-ning asosiy tushunchalari va eng yaxshi amaliyotlarini tushunish bugungi murakkab taqsimlangan muhitlarda mustahkam va ishonchli dasturiy ta'minotni ishlab chiqish uchun zarurdir.
Ushbu qo'llanmada ko'rsatilgan printsiplarni amalga oshirish orqali siz butun dunyo bo'ylab qamrab olishingizdan qat'iy nazar, nosozliklarga chidamliroq Python ilovalarini yaratishingiz, yaxshiroq foydalanuvchi tajribasini va yanada barqaror tizimni ta'minlashingiz mumkin.